{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Introduction to the pandapower control module"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial introduces the pandapower controle module with the example of tap changer control. For this, we first load the MV oberrhein network that contains two 110/20 kV transformers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>std_type</th>\n",
       "      <th>hv_bus</th>\n",
       "      <th>lv_bus</th>\n",
       "      <th>sn_mva</th>\n",
       "      <th>vn_hv_kv</th>\n",
       "      <th>vn_lv_kv</th>\n",
       "      <th>vk_percent</th>\n",
       "      <th>vkr_percent</th>\n",
       "      <th>pfe_kw</th>\n",
       "      <th>...</th>\n",
       "      <th>tap_neutral</th>\n",
       "      <th>tap_min</th>\n",
       "      <th>tap_max</th>\n",
       "      <th>tap_step_percent</th>\n",
       "      <th>tap_step_degree</th>\n",
       "      <th>tap_pos</th>\n",
       "      <th>tap_phase_shifter</th>\n",
       "      <th>parallel</th>\n",
       "      <th>df</th>\n",
       "      <th>in_service</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>114</td>\n",
       "      <td>HV/MV Transformer 0</td>\n",
       "      <td>25 MVA 110/20 kV</td>\n",
       "      <td>58</td>\n",
       "      <td>39</td>\n",
       "      <td>25.0</td>\n",
       "      <td>110.0</td>\n",
       "      <td>20.0</td>\n",
       "      <td>11.2</td>\n",
       "      <td>0.282</td>\n",
       "      <td>29.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>-9</td>\n",
       "      <td>9</td>\n",
       "      <td>1.5</td>\n",
       "      <td>NaN</td>\n",
       "      <td>-2</td>\n",
       "      <td>False</td>\n",
       "      <td>1</td>\n",
       "      <td>1.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>142</td>\n",
       "      <td>HV/MV Transformer 1</td>\n",
       "      <td>25 MVA 110/20 kV</td>\n",
       "      <td>318</td>\n",
       "      <td>319</td>\n",
       "      <td>25.0</td>\n",
       "      <td>110.0</td>\n",
       "      <td>20.0</td>\n",
       "      <td>11.2</td>\n",
       "      <td>0.282</td>\n",
       "      <td>29.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>-9</td>\n",
       "      <td>9</td>\n",
       "      <td>1.5</td>\n",
       "      <td>NaN</td>\n",
       "      <td>-3</td>\n",
       "      <td>False</td>\n",
       "      <td>1</td>\n",
       "      <td>1.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2 rows × 23 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                    name          std_type  hv_bus  lv_bus  sn_mva  vn_hv_kv  \\\n",
       "114  HV/MV Transformer 0  25 MVA 110/20 kV      58      39    25.0     110.0   \n",
       "142  HV/MV Transformer 1  25 MVA 110/20 kV     318     319    25.0     110.0   \n",
       "\n",
       "     vn_lv_kv  vk_percent  vkr_percent  pfe_kw  ...  tap_neutral  tap_min  \\\n",
       "114      20.0        11.2        0.282    29.0  ...            0       -9   \n",
       "142      20.0        11.2        0.282    29.0  ...            0       -9   \n",
       "\n",
       "    tap_max  tap_step_percent  tap_step_degree  tap_pos  tap_phase_shifter  \\\n",
       "114       9               1.5              NaN       -2              False   \n",
       "142       9               1.5              NaN       -3              False   \n",
       "\n",
       "     parallel   df  in_service  \n",
       "114         1  1.0        True  \n",
       "142         1  1.0        True  \n",
       "\n",
       "[2 rows x 23 columns]"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Importing necessary packages\n",
    "import pandapower as pp\n",
    "from pandapower.networks import mv_oberrhein\n",
    "\n",
    "net = mv_oberrhein()\n",
    "net.trafo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we run a power flow, we can see the voltage at the low voltage side of the transformers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "114    1.014598\n",
       "142    1.028804\n",
       "Name: vm_lv_pu, dtype: float64"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pp.runpp(net)\n",
    "net.res_trafo.vm_lv_pu"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Both transformers include a tap changer with a range of -9 to +9, which are set to positions -2 and -3 respectively:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "114   -2\n",
       "142   -3\n",
       "Name: tap_pos, dtype: int32"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.trafo[\"tap_pos\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The tap position is constant within a power flow calculation. A controller can now be used to control the tap changer position depending on the bus voltage."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Discrete Tap Control"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The DiscreteTapControl from the pandapower control package receives a deadband of permissable voltage and uses the tap changer to keep the voltage within this voltage band. We define such a controller for the first transformer in the oberrhein network with a deadband of 0.99 to 1.01pu:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandapower.control as control\n",
    "trafo_controller = control.DiscreteTapControl(net=net, tid=114, vm_lower_pu=0.99, vm_uppe_pur=1.01)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The initiated controller automatically registers in the net. It can be found in the controller table:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>controller</th>\n",
       "      <th>in_service</th>\n",
       "      <th>order</th>\n",
       "      <th>level</th>\n",
       "      <th>recycle</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>DiscreteTapControl of trafo 114</td>\n",
       "      <td>True</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                        controller  in_service  order level  recycle\n",
       "0  DiscreteTapControl of trafo 114        True    0.0     0    False"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.controller"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We now run a controlled power flow by setting **run_control=True** within the runpp arguments and check the transformer voltage:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "114    0.998267\n",
       "142    1.028804\n",
       "Name: vm_lv_pu, dtype: float64"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# running a control-loop\n",
    "pp.runpp(net, run_control=True)\n",
    "net.res_trafo.vm_lv_pu"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The voltage at transformer 114 is now within the given range. If we checke the transformer table, we can see that the tap position of the first transformer as been changed from -2 to -1:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "114   -1\n",
       "142   -3\n",
       "Name: tap_pos, dtype: int32"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.trafo[\"tap_pos\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Continous Tap Control\n",
    "\n",
    "It is also possible to control transformer with a **ContiniousTapControl** strategy. Instead of a range, this type of controller is able to achieve an exact output voltage. For this it assumes tap positions as floating numbers. We define such a controller for the second transformer in the network:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [],
   "source": [
    "trafo_controller = control.ContinuousTapControl(net=net, tid=142, vm_set_pu=0.98, tol=1e-6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we now run the result, the low voltage side of the second transformer is controlled to exactly 0.98 pu:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "114    0.998267\n",
       "142    0.980000\n",
       "Name: vm_lv_pu, dtype: float64"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pp.runpp(net, run_control=True)\n",
    "net.res_trafo.vm_lv_pu"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The tap position is set to -0.07:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "114   -1.000000\n",
       "142   -0.067373\n",
       "Name: tap_pos, dtype: float64"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.trafo[\"tap_pos\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "While this obviously would not possible in real transformers, it can be useful to assume continous taps in large scale studies to avoid big steps in the results."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
